package com.bii.gelapp;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Hashtable;

import org.opencv.android.Utils;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.imgproc.Imgproc;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap.Config;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;

public class MarkerSegmentationActivity extends Activity {
	public Bitmap originalBmp; // origin
	public static Bitmap activeBmp; // edited image
	public static Bitmap takenBmp;
	public static Bitmap grayBmp;
	
	ImageView ivImage;
	EditText etMinsize;
	Button btEdge, btPrev, btCompare;
	int minsize = 450;
	
	Mat destImg;
	//15 september
	int counterup = 0;
	int counterdown = 0;

	ArrayList<ConnectedComponent> markerlist = new ArrayList<ConnectedComponent>();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.markersegmentationactivity);
		LinearLayout myLayout = (LinearLayout) findViewById(R.id.segmentationlayout);
		myLayout.requestFocus();

		ivImage = (ImageView) findViewById(R.id.ivImage);
		byte[] byteArray = getIntent().getByteArrayExtra("BMP");
		originalBmp = BitmapFactory.decodeByteArray(byteArray, 0,
				byteArray.length);

		if (getIntent().hasExtra("markerlist")) {
			ArrayList<ConnectedComponent> markerlistedited = (ArrayList<ConnectedComponent>) getIntent()
					.getSerializableExtra("markerlist");

			if (markerlistedited.size() != 0) {
				markerlist.clear();

				// Collections.copy(markerlist, markerlistedited);
				for (int i = 0; i < markerlistedited.size(); i++) {
					markerlist.add(markerlistedited.get(i));
				}
			}
		}

		// from fullscreen
		if (getIntent().hasExtra("activeBmp")) {
			byte[] byteArrayActive = getIntent().getByteArrayExtra("activeBmp");
			if (byteArrayActive.length != 0) {
				activeBmp = BitmapFactory.decodeByteArray(byteArrayActive, 0,
						byteArrayActive.length);
				// Bitmap resizedbmp = Bitmap.createScaledBitmap(activeBmp, 300,
				// 300, true);
				ivImage.setImageBitmap(activeBmp);
			} else {
				activeBmp = originalBmp;
				// Bitmap resizedbmp = Bitmap.createScaledBitmap(originalBmp,
				// 300,
				// 300, true);
				ivImage.setImageBitmap(activeBmp);
			}
		} else {
			activeBmp = originalBmp;
			// Bitmap resizedbmp = Bitmap.createScaledBitmap(originalBmp, 300,
			// 300, true);
			ivImage.setImageBitmap(activeBmp);
		}

		etMinsize = (EditText) findViewById(R.id.etMinsize);
		etMinsize.setText("" + 450);
		etMinsize.setHint("size to segment fragments");

		btEdge = (Button) findViewById(R.id.btEdge);

		btEdge.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				takenBmp = originalBmp;
				Mat srcImg = new Mat(takenBmp.getHeight(), takenBmp.getWidth(),
						CvType.CV_8U, new Scalar(4));
				int ch = srcImg.channels();
				// Bitmap myBitmap32 = takenBmp.copy(Bitmap.Config.ARGB_8888,
				// true);
				Utils.bitmapToMat(takenBmp, srcImg);
				Imgproc.cvtColor(srcImg, srcImg, Imgproc.COLOR_BGR2GRAY);
				ch = srcImg.channels();
				// Imgproc.Canny(SegmentationActivity.takenBmp,
				// SegmentationActivity.activeBmp, 10.0, 20.0);
				ArrayList<ConnectedComponent> connectedComponentList = new ArrayList<ConnectedComponent>();
				destImg = new Mat();
				Imgproc.cvtColor(srcImg, destImg, Imgproc.COLOR_GRAY2BGR);

				int w = srcImg.width();
				int h = srcImg.height();

				minsize = Integer.parseInt(etMinsize.getText().toString());
				// store in markerlist
				markerlist.clear();

				connectedComponentList.clear();
				findConnectedComponents(srcImg, destImg,
						connectedComponentList, minsize);
				Bitmap segmentedBmp = Bitmap.createBitmap(destImg.cols(),
						destImg.rows(), Bitmap.Config.RGB_565);
				Utils.matToBitmap(destImg, segmentedBmp);
				activeBmp = segmentedBmp;
				// Bitmap resizedbmp = Bitmap.createScaledBitmap(segmentedBmp,
				// 300, 300, true);
				ivImage.setImageBitmap(activeBmp);
				
				// gray test
				// convert bitmap to matrix
				grayBmp = MarkerGaborActivity2.colorBmp
						.copy(Config.ARGB_8888, true);
				srcImg = new Mat(grayBmp.getHeight(), grayBmp.getWidth(),
						CvType.CV_8U, new Scalar(4));
				Bitmap myBitmap32 = grayBmp.copy(Bitmap.Config.ARGB_8888, true);
				Utils.bitmapToMat(myBitmap32, srcImg);
				Imgproc.cvtColor(srcImg, destImg, Imgproc.COLOR_BGR2GRAY);
				grayBmp = Bitmap.createBitmap(destImg.cols(), destImg.rows(),
						Bitmap.Config.RGB_565);
				Utils.matToBitmap(destImg, grayBmp);
				// convert to grayscale
				Mat grayImg = new Mat();

				fixRectangles();
				//fixRectangles2();

				// convert mat back to bitmap set originalBmp

				drawRectangles();
				Utils.matToBitmap(destImg, grayBmp);
				//Bitmap resizedbmp1 = Bitmap.createScaledBitmap(grayBmp, 300,
				//		300, true);
				ivImage.setImageBitmap(grayBmp);
			}
		});

		btPrev = (Button) findViewById(R.id.btPrev);
		btPrev.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				startActivity(new Intent(MarkerSegmentationActivity.this,
						MarkerGaborActivity.class));

			}
		});

		btCompare = (Button) findViewById(R.id.btCompare);
		btCompare.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				Intent goToNextActivity = new Intent(getApplicationContext(),
						MarkerCompareActivity.class);
				// byte[] bytes;
				// bytes = compressImage(activeBmp);
				// byte[] bytes1;
				// bytes1 = compressImage(originalBmp);
				// goToNextActivity.putExtra("BMP1", bytes1);
				// goToNextActivity.putExtra("BMP", bytes);

				goToNextActivity.putExtra("markerlist", markerlist);
				startActivity(goToNextActivity);

			}
		});

	}

	public void findConnectedComponents(Mat srcImg, Mat destImg,
			ArrayList<ConnectedComponent> connectedComponentList, int minArea) {
		Hashtable<Integer, ConnectedComponent> conCompHt = new Hashtable<Integer, ConnectedComponent>();// from
																										// label
																										// to
																										// connected
																										// component
		int[][] labelMatrix = new int[srcImg.height()][srcImg.width()]; // all
																		// elements
																		// will
																		// be
																		// initialized
																		// with
																		// 0
		int issuedLabel = 0;

		System.out.println("Start finding connected components...");

		int temp = 0;
		for (int i = 1; i < srcImg.height() - 1; i++) {
			for (int j = 1; j < srcImg.width() - 1; j++) {
				double[] data = srcImg.get(i, j);
				if (data[0] <= 50) { // black pixel
					if (labelMatrix[i][j - 1] != 0) {// the left neighbour pixel
														// has label (and of
														// course is black
														// pixel)
						labelMatrix[i][j] = labelMatrix[i][j - 1]; // label
																	// pixel
																	// (i,j),
																	// and admit
																	// it to the
																	// left
																	// neighbor
																	// pixel's
																	// connected
																	// component
						// UPDATE THE CONNECTED COMPONENT
						ConnectedComponent conComp = conCompHt
								.get(labelMatrix[i][j - 1]);
						if (conComp == null) {
							System.out.println(i + "\t" + j + "\t"
									+ labelMatrix[i][j]);
							System.out.println(labelMatrix[i][j - 1]);
							/*
							 * for (int g= 12;g<26;g++){ for (int f= 540; f<560;
							 * f++){ System.out.print(srcImg.get(g, f)[0]+"\t");
							 * } System.out.println(); }
							 * 
							 * for (int g= 12;g<26;g++){ for (int f= 540; f<560;
							 * f++){ System.out.print(labelMatrix[g][f]+"\t"); }
							 * System.out.println(); }
							 */
						}
						conComp.noPixels++;
						if (conComp.right < j)
							conComp.right = j;// no need to update the left, top
												// and bottom boundaries of the
												// connected component
						conCompHt.put(labelMatrix[i][j - 1], conComp);

						// MERGING THE CONNECTED COMPONENT WITH ITS NEIGHBOUR
						// CONNECTED COMPONENTS (If existing any)
						ConnectedComponent neighbourConComp;
						if (labelMatrix[i - 1][j - 1] != 0
								&& labelMatrix[i - 1][j - 1] != labelMatrix[i][j - 1]) {
							temp = labelMatrix[i - 1][j - 1];
							for (int e = j - 1; e < srcImg.width(); e++) {// update
																			// the
																			// labels
																			// of
																			// all
																			// pixels
																			// at
																			// the
																			// same
																			// line
																			// and
																			// have
																			// the
																			// same
																			// label
																			// as
																			// pixel
																			// (i-1,j-1)
								if (labelMatrix[i - 1][e] == temp)
									labelMatrix[i - 1][e] = labelMatrix[i][j - 1];
							}
							for (int e = j - 2; e > 0; e--) {// update the
																// labels of all
																// pixels at the
																// same line as
																// pixel (i,j)
																// and have the
																// same label as
																// pixel
																// (i-1,j-1)
								if (labelMatrix[i][e] == temp)
									labelMatrix[i][e] = labelMatrix[i][j - 1];
							}

							neighbourConComp = conCompHt.get(temp);
							conComp.noPixels += neighbourConComp.noPixels;
							if (neighbourConComp.left < conComp.left)
								conComp.left = neighbourConComp.left;
							if (neighbourConComp.right > conComp.right)
								conComp.right = neighbourConComp.right;
							if (neighbourConComp.top < conComp.top)
								conComp.top = neighbourConComp.top;// no need to
																	// update
																	// the
																	// bottom
																	// boundary
							conCompHt.put(labelMatrix[i][j - 1], conComp);
							conCompHt.remove(temp);// delete the neighbour
													// conComp after it is
													// merged
						}
						if (labelMatrix[i - 1][j] != 0
								&& labelMatrix[i - 1][j] != labelMatrix[i][j - 1]) {
							temp = labelMatrix[i - 1][j];
							for (int e = j; e < srcImg.width(); e++) {// update
																		// the
																		// labels
																		// of
																		// all
																		// pixels
																		// at
																		// the
																		// same
																		// line
																		// and
																		// have
																		// the
																		// same
																		// label
																		// as
																		// pixel
																		// (i-1,j)
								if (labelMatrix[i - 1][e] == temp)
									labelMatrix[i - 1][e] = labelMatrix[i][j - 1];
							}
							for (int e = j - 2; e > 0; e--) {// update the
																// labels of all
																// pixels at the
																// same line as
																// pixel (i,j)
																// and have the
																// same label as
																// pixel (i-1,j)
								if (labelMatrix[i][e] == temp)
									labelMatrix[i][e] = labelMatrix[i][j - 1];
							}

							neighbourConComp = conCompHt.get(temp);
							conComp.noPixels += neighbourConComp.noPixels;
							if (neighbourConComp.left < conComp.left)
								conComp.left = neighbourConComp.left;
							if (neighbourConComp.right > conComp.right)
								conComp.right = neighbourConComp.right;
							if (neighbourConComp.top < conComp.top)
								conComp.top = neighbourConComp.top;// no need to
																	// update
																	// the
																	// bottom
																	// boundary
							conCompHt.put(labelMatrix[i][j - 1], conComp);

							conCompHt.remove(temp);// delete the neighbour
													// conComp after it is
													// merged
						}
						// Log.d("tag1", i + " " + j);
						if (labelMatrix[i - 1][j + 1] != 0
								&& labelMatrix[i - 1][j + 1] != labelMatrix[i][j - 1]) {
							temp = labelMatrix[i - 1][j + 1];
							for (int e = j + 1; e < srcImg.width(); e++) {// update
																			// the
																			// labels
																			// of
																			// all
																			// pixels
																			// at
																			// the
																			// same
																			// line
																			// and
																			// have
																			// the
																			// same
																			// label
																			// as
																			// pixel
																			// (i-1,j+1)
								if (labelMatrix[i - 1][e] == temp)
									labelMatrix[i - 1][e] = labelMatrix[i][j - 1];
							}
							for (int e = j - 2; e > 0; e--) {// update the
																// labels of all
																// pixels at the
																// same line as
																// pixel (i,j)
																// and have the
																// same label as
																// pixel
																// (i-1,j+1)
								if (labelMatrix[i][e] == temp)
									labelMatrix[i][e] = labelMatrix[i][j - 1];
							}

							neighbourConComp = conCompHt.get(temp);
							conComp.noPixels += neighbourConComp.noPixels;
							if (neighbourConComp.left < conComp.left)
								conComp.left = neighbourConComp.left;
							if (neighbourConComp.right > conComp.right)
								conComp.right = neighbourConComp.right;
							if (neighbourConComp.top < conComp.top)
								conComp.top = neighbourConComp.top;// no need to
																	// update
																	// the
																	// bottom
																	// boundary
							conCompHt.put(labelMatrix[i][j - 1], conComp);
							conCompHt.remove(temp);// delete the neighbour
													// conComp after it is
													// merged
						}
					} else if (labelMatrix[i - 1][j - 1] != 0) {// the top-left
																// neighbour
																// pixel has
																// label (and of
																// course is
																// black pixel)
						labelMatrix[i][j] = labelMatrix[i - 1][j - 1]; // label
																		// pixel
																		// (i,j),
																		// and
																		// admit
																		// it to
																		// the
																		// top-left
																		// neighbor
																		// pixel's
																		// connected
																		// component
						// UPDATE THE CONNECTED COMPONENT
						ConnectedComponent conComp = conCompHt
								.get(labelMatrix[i - 1][j - 1]);
						conComp.noPixels++;
						if (conComp.right < j)
							conComp.right = j;
						if (conComp.bottom < i)
							conComp.bottom = i;// no need to update the left and
												// top boundaries of the
												// connected component
						conCompHt.put(labelMatrix[i - 1][j - 1], conComp);

						// MERGING THE CONNECTED COMPONENT WITH ITS NEIGHBOUR
						// CONNECTED COMPONENTS (If existing any)
						ConnectedComponent neighbourConComp;
						if (labelMatrix[i - 1][j] != 0
								&& labelMatrix[i - 1][j] != labelMatrix[i - 1][j - 1]) {
							// This will never happen because
							// labelMatrix[i-1][j] must become equal to
							// labelMatrix[i-1][j-1]
							// when line (i-1) was scanned previously
						}
						if (labelMatrix[i - 1][j + 1] != 0
								&& labelMatrix[i - 1][j + 1] != labelMatrix[i - 1][j - 1]) {
							temp = labelMatrix[i - 1][j + 1];
							for (int e = j + 1; e < srcImg.width(); e++) {// update
																			// the
																			// labels
																			// of
																			// all
																			// pixels
																			// at
																			// the
																			// same
																			// line
																			// and
																			// have
																			// the
																			// same
																			// label
																			// as
																			// pixel
																			// (i-1,j+1)
								if (labelMatrix[i - 1][e] == temp)
									labelMatrix[i - 1][e] = labelMatrix[i - 1][j - 1];
							}
							for (int e = j - 2; e > 0; e--) {// update the
																// labels of all
																// pixels at the
																// same line as
																// pixel (i,j)
																// and have the
																// same label as
																// pixel
																// (i-1,j+1)
								if (labelMatrix[i][e] == temp)
									labelMatrix[i][e] = labelMatrix[i - 1][j - 1];
							}

							neighbourConComp = conCompHt.get(temp);
							conComp.noPixels += neighbourConComp.noPixels;
							if (neighbourConComp.left < conComp.left)
								conComp.left = neighbourConComp.left;
							if (neighbourConComp.right > conComp.right)
								conComp.right = neighbourConComp.right;
							if (neighbourConComp.top < conComp.top)
								conComp.top = neighbourConComp.top;// no need to
																	// update
																	// the
																	// bottom
																	// boundary
							conCompHt.put(labelMatrix[i][j - 1], conComp);
							conCompHt.remove(temp);// delete the neighbour
													// conComp after it is
													// merged
						}

					} else if (labelMatrix[i - 1][j] != 0) {// the top neighbour
															// pixel has label
															// (and of course is
															// black pixel)
						labelMatrix[i][j] = labelMatrix[i - 1][j]; // label
																	// pixel
																	// (i,j),
																	// and admit
																	// it to the
																	// top
																	// neighbour
																	// pixel's
																	// connected
																	// component
						// UPDATE THE CONNECTED COMPONENT
						ConnectedComponent conComp = conCompHt
								.get(labelMatrix[i - 1][j]);
						conComp.noPixels++;
						if (conComp.bottom < i)
							conComp.bottom = i;// no need to update the left,
												// right and top boundaries of
												// the connected component
						conCompHt.put(labelMatrix[i - 1][j], conComp);

						// MERGING THE CONNECTED COMPONENT WITH ITS NEIGHBOUR
						// CONNECTED COMPONENTS (If existing any)
						// ConnectedComponent neighbourConComp;
						if (labelMatrix[i - 1][j + 1] != 0
								&& labelMatrix[i - 1][j + 1] != labelMatrix[i - 1][j]) {
							// This will never happen because
							// labelMatrix[i-1][j+1] must become equal to
							// labelMatrix[i-1][j]
							// when line (i-1) was scanned previously
						}
					} else if (labelMatrix[i - 1][j + 1] != 0) {// the top-right
																// neighbour
																// pixel has
																// label (and of
																// course is
																// black pixel)
						labelMatrix[i][j] = labelMatrix[i - 1][j + 1]; // label
																		// pixel
																		// (i,j),
																		// and
																		// admit
																		// it to
																		// the
																		// top-right
																		// neighbour
																		// pixel's
																		// connected
																		// component
						// UPDATE THE CONNECTED COMPONENT
						ConnectedComponent conComp = conCompHt
								.get(labelMatrix[i - 1][j + 1]);
						conComp.noPixels++;
						if (conComp.bottom < i)
							conComp.bottom = i;// no need to update the left,
												// right and top boundaries of
												// the connected component
						if (conComp.left > j)
							conComp.left = j;
						conCompHt.put(labelMatrix[i - 1][j + 1], conComp);
					} else {// there is none black pixels among the 4 neighbour
							// pixels of pixel (i,j)
							// CREATE A NEW CONNECTED COMPONENT FOR pixel (i,j)
						issuedLabel++;
						labelMatrix[i][j] = issuedLabel;
						ConnectedComponent conComp = new ConnectedComponent();
						conComp.noPixels = 1;
						conComp.label = issuedLabel;
						conComp.left = conComp.right = j;
						conComp.top = conComp.bottom = i;
						conCompHt.put(labelMatrix[i][j], conComp);
					}
				}// end if (data[0]<=50){ //pixel (i,j) is black
			}// end for j
		}// end for i
		System.out.println("Finnished finding connected components.");

		// LISTING ALL THE CONNECTED COMPONENTS
		Enumeration<Integer> en = conCompHt.keys();
		int label = 0;
		while (en.hasMoreElements()) {
			label = en.nextElement();
			connectedComponentList.add(conCompHt.get(label));
		}

		// update the connectedcomponent to offset the gabor filtering
		/*for (int i = 0; i < connectedComponentList.size(); i++) {
			ConnectedComponent cc = connectedComponentList.get(i);
			cc.top = cc.top + 8;
			cc.bottom = cc.bottom + 8;
		}*/

		// DRAW ALL THE CONNECTED COMPONENTS TO destImg (using rectangle bounds)
		//uh, no don't draw
		for (int i = 0; i < connectedComponentList.size(); i++) {
			if (connectedComponentList.get(i).noPixels >= minArea) {
				/*Core.rectangle(destImg, new Point(
						connectedComponentList.get(i).left,
						connectedComponentList.get(i).top - 12), new Point(
						connectedComponentList.get(i).right,
						connectedComponentList.get(i).bottom -12), new Scalar(255,
						0, 0), 2);*/
				markerlist.add(connectedComponentList.get(i));
			}

		}

		System.out.println("Finnished drawing connected components.");

	}
	
	public void drawRectangles() {
		

		for (int j = 0; j < markerlist.size(); j++) {
			int top = markerlist.get(j).top;
			int bottom = markerlist.get(j).bottom;

			int left = markerlist.get(j).left;
			int right = markerlist.get(j).right;
			Core.rectangle(destImg, new Point(left, top), new Point(right,
					bottom), new Scalar(255, 255, 0), 2);

			int centerheight = (bottom + top) / 2;
			int centerwidth = (left + right)/2;
			Point org = new Point(centerwidth, centerheight);

			Core.putText(destImg, "" + j, org, 3, 1, new Scalar(0, 255, 0), 5);

		}

	}
	
	public void fixRectangles() {
		Mat srcImg = new Mat(grayBmp.getHeight(), grayBmp.getWidth(),
				CvType.CV_8U, new Scalar(4));
		Bitmap myBitmap32 = grayBmp.copy(Bitmap.Config.ARGB_8888, true);
		Utils.bitmapToMat(myBitmap32, srcImg);

		// get initial intensity average
		for (int i = 0; i < markerlist.size(); i++) {
			int averageFragmentIntensity = 0;
			int j = 0;
			int k = 0;

			for (j = 0; j + markerlist.get(i).left <= markerlist.get(i).right; j++) {
				for (k = 0; k + markerlist.get(i).top <= markerlist.get(i).bottom; k++) {
					double[] intensity = srcImg.get(markerlist.get(i).top + k,
							markerlist.get(i).left + j);
					averageFragmentIntensity += intensity[0];
				}
			}
			// test upwards first
			averageFragmentIntensity = averageFragmentIntensity
					/ ((markerlist.get(i).right - markerlist.get(i).left) * (markerlist
							.get(i).bottom - markerlist.get(i).top));
			upwardsTest(averageFragmentIntensity, markerlist.get(i), srcImg);
			downwardsTest(averageFragmentIntensity, markerlist.get(i), srcImg);
		}

	}
	
	private void upwardsTest(int initialavg, ConnectedComponent cc, Mat srcImg) {
		boolean status = false;
		int initialtestavg = initialavg;
		// initial moving up of one pixel
		cc.top -= 1;
		cc.bottom -= 1;
		while (status != true) {
			int testavg = 0;
			int j = 0;
			int k = 0;
			for (j = 0; j + cc.left <= cc.right; j++) {

				for (k = 0; k + cc.top <= cc.bottom; k++) {
					double[] intensity = srcImg.get(cc.top + k, cc.left + j);
					testavg += intensity[0];
				}

			}
			testavg = testavg / ((cc.right - cc.left) * (cc.bottom - cc.top));
			if (testavg <= initialtestavg) {
				initialtestavg = testavg;
				status = false;
				cc.top -= 1;
				cc.bottom -= 1;
			} else {
				status = true;
			}
		}
	}

	private void downwardsTest(int initialavg, ConnectedComponent cc, Mat srcImg) {
		boolean status = false;
		int initialtestavg = initialavg;
		// initial moving up of one pixel
		cc.top += 1;
		cc.bottom += 1;
		while (status != true) {
			int testavg = 0;
			int j = 0;
			int k = 0;

			for (j = 0; j + cc.left <= cc.right; j++) {
					for (k = 0; k + cc.top <= cc.bottom; k++) {
						// int intensity =
						// grayBmp.getPixel(componentlist.get(i).left + j,
						// componentlist.get(i).top + k);
						
						double[] intensity = srcImg
								.get(cc.top + k, cc.left + j);
						testavg += intensity[0];
						
						
					}

			}
			testavg = testavg / ((cc.right - cc.left) * (cc.bottom - cc.top));
			if(cc.bottom + 1 >= grayBmp.getHeight()){
				status = true;
			}
			else
			{
				if (testavg <= initialtestavg) {
					initialtestavg = testavg;
					status = false;
					cc.top += 1;
					cc.bottom += 1;
				}
				else {
					status = true;
				}
			}
		}
	}
	
	public void fixRectangles2() {
		Mat srcImg = new Mat(grayBmp.getHeight(), grayBmp.getWidth(),
				CvType.CV_8U, new Scalar(4));
		Bitmap myBitmap32 = grayBmp.copy(Bitmap.Config.ARGB_8888, true);
		Utils.bitmapToMat(myBitmap32, srcImg);
		
		//
		destImg = srcImg;
		
		ArrayList markerintensityList = new ArrayList();
		int averagemarkerIntensity = 0;
		for (int i = 0; i < markerlist.size(); i++) {
			for (int j = 0; j + markerlist.get(i).top <= markerlist
					.get(i).bottom; j++) {
				int rowintensity = 0;
				for (int k = 0; k + markerlist.get(i).left <= markerlist
						.get(i).right; k++) {
					double[] intensity = srcImg.get(markerlist.get(i).top,
							markerlist.get(i).left + k);
					rowintensity += intensity[0];
				}
				Log.d("tag1", "index: " + i);
				markerintensityList.add(rowintensity);
				averagemarkerIntensity += rowintensity;
			}
			
			averagemarkerIntensity = averagemarkerIntensity
					/ ((markerlist.get(i).right - markerlist.get(i).left) * (markerlist
							.get(i).bottom - markerlist.get(i).top));
			counterup = 0;
			counterdown = 0;
			//test upwards	
			int upresult = upwardsTest2(markerintensityList, averagemarkerIntensity, markerlist.get(i), srcImg);
			//test downwards
			int downresult = downwardsTest2(markerintensityList, averagemarkerIntensity, markerlist.get(i), srcImg);
			
			if(upresult < downresult)
			{
				markerlist.get(i).top -= counterup;
				markerlist.get(i).bottom -= counterup;
			}
			else if(upresult == downresult){
				if(counterup < counterdown)
				{
					markerlist.get(i).top -= counterup;
					markerlist.get(i).bottom -= counterup;
				}
				else
				{
					markerlist.get(i).top += counterdown;
					markerlist.get(i).bottom += counterdown;
				}
			}
			else
			{
				markerlist.get(i).top += counterdown;
				markerlist.get(i).bottom += counterdown;
			}
			
			//drawRectangles();
		}
		
	}

	private int upwardsTest2(ArrayList initialintensitylist, int averageFragmentIntensity, ConnectedComponent cc, Mat srcImg) {
		boolean status = false;
		ArrayList testintensitylist = initialintensitylist;
		//test fragmentIntensity with testfragmentIntensity
		int testfragmentIntensity = averageFragmentIntensity;
		
		while(status != true)
		{
			int fragmentIntensity = 0;
			//cc.top -= 1;
			//cc.bottom -= 1;
			counterup ++;
			
			int rowintensity = 0;
			for (int k = 0; k + cc.left <= cc.right; k++) {
				if(cc.top - counterup >= 0){
					double[] intensity = srcImg.get(cc.top - counterup, cc.left + k);
					rowintensity += intensity[0];
				}
				else
				{
					status = true;
					break;
				}
				
			}
			//upwards add top
			testintensitylist.add(0, rowintensity);
			//upwards remove bottom
			testintensitylist.remove(testintensitylist.size() - 1);
			
			for(int i = 0; i < testintensitylist.size(); i++){
				fragmentIntensity += (Integer)testintensitylist.get(i);
			}
			//average
			fragmentIntensity = fragmentIntensity
					/ ((cc.right - cc.left) * ((cc.bottom - counterup) - (cc.top - counterup)));
			Log.d("tag1", "upwards average intensity: " + fragmentIntensity);
			//if brighter, continue to loop
			if (fragmentIntensity <= testfragmentIntensity) {
				//replace testfragmentIntensity with fragmentIntensity
				testfragmentIntensity = fragmentIntensity;
				status = false;
			} else {
				status = true;
			}
			
		}
		return testfragmentIntensity;
	}

	private int downwardsTest2(ArrayList initialintensitylist, int averageFragmentIntensity, ConnectedComponent cc, Mat srcImg) {
		boolean status = false;
		ArrayList testintensitylist = initialintensitylist;
		//test fragmentIntensity with testfragmentIntensity
		int testfragmentIntensity = averageFragmentIntensity;
		
		while(status != true)
		{
			int fragmentIntensity = 0;
			//cc.top += 1;
			//cc.bottom += 1;
			counterdown ++;
			
			int rowintensity = 0;
			for (int k = 0; k + cc.left <= cc.right; k++) {
				//reverse the calculation
				if(cc.top - counterup <= grayBmp.getHeight()){
					double[] intensity = srcImg.get(cc.bottom + counterdown, cc.left + k);
					rowintensity += intensity[0];
				}
				else
				{
					status = true;
					break;
				}
			}
			//downwards add bottom
			testintensitylist.add(rowintensity);
			//downwards remove top
			testintensitylist.remove(0);
			
			for(int i = 0; i < testintensitylist.size(); i++){
				fragmentIntensity += (Integer)testintensitylist.get(i);
			}
			//average
			fragmentIntensity = fragmentIntensity
					/ ((cc.right - cc.left) * ((cc.bottom + counterdown) - (cc.top + counterdown)));
			Log.d("tag1", "downwards average intensity: " + fragmentIntensity);
			//if brighter, continue to loop
			if (fragmentIntensity <= testfragmentIntensity) {
				//replace testfragmentIntensity with fragmentIntensity
				testfragmentIntensity = fragmentIntensity;
				status = false;
			} else {
				status = true;
				
			}
		}
		return testfragmentIntensity;
			
	}

	public byte[] compressImage(Bitmap image) {
		ByteArrayOutputStream stream = new ByteArrayOutputStream();
		image.compress(Bitmap.CompressFormat.PNG, 0, stream);
		byte[] bytes = stream.toByteArray();
		return bytes;
	}
}
